package com.ccb.sc.payment.controller;

import com.google.common.collect.Lists;
import com.ccb.sc.auth.TokenAuth;
import com.ccb.sc.auth.TokenModel;
import com.ccb.sc.payment.plugin.AbstractPaymentPlugin;
import com.ccb.sc.payment.service.IPaymentPluginService;
import com.ccb.sc.payment.service.IPaymentService;
import com.ccb.sc.payment.vo.PaymentResultVo;
import com.ccb.sc.payment.vo.QueryResultVo;
import com.ccb.sc.common.bind.annotation.CurrentUser;
//psl import com.ccb.sc.common.bind.exception.BizException;
import com.ccb.sc.common.bind.response.ResBody;
import com.ccb.sc.common.code.BizCodeFace;
import com.ccb.sc.common.code.ErrorCode;
import com.ccb.sc.common.modules.member.entity.Member;
import com.ccb.sc.common.modules.member.service.MemberService;
import com.ccb.sc.common.modules.payment.entity.Payment;
import com.ccb.sc.common.modules.payment.enums.ClientType;
import com.ccb.sc.common.modules.payment.enums.PaymentStatus;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author ken
 * @version 1.0
 * @date 2020-09-27
 */
@RestController
@RequestMapping("/app/payment")
@Api(value = "支付管理", tags = "支付管理")
public class PaymentController {

    @Autowired
    private IPaymentPluginService pluginService;

    @Autowired
    private IPaymentService paymentService;

    @Autowired
    private MemberService memberService;

    @GetMapping("/methods")
    @TokenAuth
    @ApiOperation(value = "获取在线支付方式", responseContainer = "list")
    public ResBody<?> getPaymentPlugins(@RequestParam @ApiParam(value = "支付客户端类型", defaultValue = "wxma") ClientType clientType) {
        List<AbstractPaymentPlugin> plugins =  this.pluginService.getPaymentPlugins(true, clientType.name());
        if (CollectionUtils.isEmpty(plugins)) {
            return ResBody.success(Lists.newArrayList());
        }
        List<Map<String,Object>> list = plugins.stream().map(item -> {
            Map<String, Object> result = new HashMap<>(4);
            result.put("id", item.getId());
            result.put("name", item.getPaymentName());
            result.put("logo", item.getLogo());
            result.put("description", item.getDescription());
            return result;
        }).collect(Collectors.toList());
        return ResBody.success(list);
    }

    @PostMapping("/submit")
    @TokenAuth
    @ApiOperation(value = "提交支付", response = PaymentResultVo.class)
    public ResBody<?> submit(@CurrentUser @ApiIgnore TokenModel token,
                             @RequestParam String orderId, @RequestParam String paymentPluginId,
                             @RequestParam @ApiParam(name = "订单类型 1（商城订单） 2（店主订单）", defaultValue = "1") Integer orderType,
                             @ApiIgnore HttpServletRequest request) {
        PaymentResultVo result = this.paymentService.submit(token.getId(), orderId, orderType, paymentPluginId, request);
        return ResBody.success(result);
    }

    @PostMapping("/balance/pay")
    @TokenAuth
    @ApiOperation(value = "使用余额支付")
    public ResBody<?> balancePay(@CurrentUser @ApiIgnore TokenModel tokenModel, @RequestParam String sn) {
        Assert.notNull(sn, "交易流水号不能为空");
        Member member = this.memberService.getById(tokenModel.getId());
        Payment payment = this.paymentService.getById(sn);
        if (payment != null) {
            Assert.isTrue(member.getId().equals(payment.getMemberId()), "订单异常");
            AbstractPaymentPlugin plugin = this.pluginService.getPaymentPlugin(payment.getPaymentPluginId());
            if (plugin != null) {
                Assert.isTrue(plugin.isWalletPayment(), "订单异常");
                this.paymentService.handleWalletPay(payment, member.getId());
                return ResBody.success();
            }
        }
        //psl throw new BizException(BizCodeFace.createBizCode(ErrorCode.FAIL).message("支付订单异常，不能完成支付"));
        return ResBody.failure();
    }

    /**
     * 异步通知
     *
     * @param sn 支付流水号
     * @return 状态
     */
    @RequestMapping("/notify/{sn}")
    @ApiIgnore
    public Object notify(@PathVariable String sn, HttpServletRequest request) {
        Payment payment = this.paymentService.getById(sn);
        if (payment != null) {
            AbstractPaymentPlugin plugin = this.pluginService.getPaymentPlugin(payment.getPaymentPluginId());
            if (plugin != null) {
                //如果订单已经支付完成
                if (payment.getStatus() == PaymentStatus.SUCCESS) {
                    return plugin.getNotifyMessage(sn, request);
                }
                if (plugin.verifyNotify(payment, request)) {
                    this.paymentService.handle(payment);
                    return plugin.getNotifyMessage(sn, request);
                }
            }
        }
        return "FAILURE";
    }

    @GetMapping("/query")
    @TokenAuth
    @ApiOperation("支付状态查询")
    public ResBody<?> query(@ApiParam("支付流水号") @RequestParam String sn) {
        Payment payment = this.paymentService.getById(sn);
        if (payment != null) {
            AbstractPaymentPlugin plugin = this.pluginService.getPaymentPlugin(payment.getPaymentPluginId());
            if (plugin != null) {
                //如果订单已经支付完成
                if (payment.getStatus() == PaymentStatus.SUCCESS) {
                    QueryResultVo queryResult = new QueryResultVo();
                    queryResult.setState(QueryResultVo.SUCCESS);
                    queryResult.setExtra(payment);
                    return ResBody.success(queryResult);
                }
                //通过支付通道查询的结果
                QueryResultVo result = plugin.doQuery(payment.getId());
                //成功
                if (QueryResultVo.SUCCESS.equals(result.getState())) {
                    payment.setTradeNo(result.getOutTradeNo());
                    this.paymentService.handle(payment);
                }
                return ResBody.success(result);
            }
        }
        return ResBody.failure("未找到支付单");
    }

}
